home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gdevsj48.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  8.8 KB  |  293 lines

  1. /* Copyright (C) 1990, 1992, 1993 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gdevsj48.c,v 1.2 2000/09/19 19:00:22 lpd Exp $*/
  20. /*
  21.  * StarJet SJ48 printer driver.
  22.  *
  23.  * --- derived from gdevbj10.c 1993-10-07
  24.  *                by Mats kerblom (f86ma@dd.chalmers.se).
  25.  */
  26.  
  27. #include "gdevprn.h"
  28.  
  29.  
  30. /*
  31.  * The only available resolutions (in the program) are (180,360)x(180,360).
  32.  *
  33.  * Used control codes:
  34.  *   <Esc>@    Printer reset
  35.  *   <Esc>J<n>    Make a n/180 inch linefeed
  36.  *   <Esc>\<a><b>    Move the print position (a+256b)/180 inch to the right
  37.  *   <Esc>*<m><a><b>... Print graphics; m=39: 180*180 dpi
  38.  *                    m=40: 360*180 dpi
  39.  *                    m=71: 180*360 dpi
  40.  *                    m=72: 360*360 dpi
  41.  *            a+256b columns is printed.
  42.  */
  43.  
  44. /* The device descriptor */
  45. private dev_proc_print_page(sj48_print_page);
  46. gx_device_printer far_data gs_sj48_device =
  47.   prn_device(prn_std_procs, "sj48",
  48.     80,                /* width_10ths, 8" */
  49.     105,                /* height_10ths, 10.5" */
  50.     360,                /* x_dpi */
  51.     360,                /* y_dpi */
  52.     0,0,0,0,            /* margins */
  53.     1, sj48_print_page);
  54.  
  55.  
  56. /*   This comes from the bj10/bj200 source. I don't know how it applies
  57.  *   for a StarJet.  --- Mats kerblom.
  58.  *
  59.  *
  60.  * The following is taken from the BJ200 Programmer's manual.  The top
  61.  * margin is 3mm (0.12"), and the bottom margin is 6.4mm (0.25").  The
  62.  * left and right margin depend on the type of paper -- US letter or
  63.  * A4 -- but ultimately rest on a print width of 203.2mm (8").  For letter
  64.  * paper, the left margin (and hence the right) is 6.4mm (0.25"), while
  65.  * for A4 paper, both are 3.4mm (0.13").
  66.  *
  67.  * The bottom margin requires a bit of care.  The image is printed
  68.  * as strips, each about 3.4mm wide.  We can only attain the bottom 
  69.  * margin if the final strip coincides with it.  Note that each strip
  70.  * is generated using only 48 of the available 64 jets, and the absence
  71.  * of those bottom 16 jets makes our bottom margin, in effect, about
  72.  * 1.1mm (0.04") larger.
  73.  *
  74.  * The bj200 behaves, in effect, as though the origin were at the first
  75.  * printable position, rather than the top left corner of the page, so
  76.  * we add a translation to the initial matrix to compensate for this.
  77.  *
  78.  * Except for the details of getting the margins correct, the bj200 is
  79.  * no different from the bj10e, and uses the same routine to print each
  80.  * page.
  81.  *
  82.  */
  83.  
  84.  
  85. /* Send the page to the printer. */
  86. private int
  87. sj48_print_page(gx_device_printer *pdev, FILE *prn_stream)
  88. {    int line_size = gx_device_raster((gx_device *)pdev, 0);
  89.     int xres = pdev->x_pixels_per_inch;
  90.     int yres = pdev->y_pixels_per_inch;
  91.     int mode = (yres == 180 ?
  92.             (xres == 180 ? 39 : 40) :
  93.             (xres == 180 ? 71 : 72));
  94.     int bytes_per_column = (yres == 180) ? 3 : 6;
  95.     int bits_per_column = bytes_per_column * 8;
  96.     int skip_unit = bytes_per_column * (xres == 180 ? 1 : 2); /* Skips in step of 1/180" */
  97.     byte *in = (byte *)gs_malloc(8, line_size, "sj48_print_page(in)");
  98.     byte *out = (byte *)gs_malloc(bits_per_column, line_size, "sj48_print_page(out)");
  99.     int lnum = 0;
  100.     int skip = 0;
  101.     int skips;
  102.     int code = 0;
  103.     int last_row = dev_print_scan_lines(pdev);
  104.     int limit = last_row - bits_per_column;
  105.  
  106.     if ( in == 0 || out == 0 )
  107.     {    code = gs_error_VMerror;
  108.         gs_note_error(code);
  109.         goto fin;
  110.     }
  111.  
  112.     /* Abort if the requested resolution is unsupported. */
  113.     if ((xres !=180 && xres != 360) || (yres !=180 && yres != 360))
  114.     {    code = gs_error_rangecheck;
  115.         gs_note_error(code);
  116.         goto fin;
  117.     }
  118.  
  119.     /* Initialize the printer. */
  120.     fwrite("\033@\000\000", 1, 4, prn_stream);  /* <Printer reset>, <0>, <0>. */
  121.  
  122.     /* Transfer pixels to printer.  The last row we can print is defined
  123.        by "last_row".  Only the bottom of the print head can print at the
  124.        bottom margin, and so we align the final printing pass.  The print
  125.        head is kept from moving below "limit", which is exactly one pass
  126.        above the bottom margin.  Once it reaches this limit, we make our
  127.        final printing pass of a full "bits_per_column" rows. */
  128.     while ( lnum < last_row )
  129.        {    
  130.         byte *in_data;
  131.         byte *in_end = in + line_size;
  132.         byte *out_beg = out;
  133.         byte *out_end = out + bytes_per_column * pdev->width;
  134.         byte *outl = out;
  135.         int count, bnum;
  136.  
  137.         /* Copy 1 scan line and test for all zero. */
  138.         code = gdev_prn_get_bits(pdev, lnum, in, &in_data);
  139.         if ( code < 0 ) goto xit;
  140.         /* The mem... or str... functions should be faster than */
  141.         /* the following code, but all systems seem to implement */
  142.         /* them so badly that this code is faster. */
  143.            {    register const long *zip = (const long *)in_data;
  144.             register int zcnt = line_size;
  145.             register const byte *zipb;
  146.             for ( ; zcnt >= 4 * sizeof(long); zip += 4, zcnt -= 4 * sizeof(long) )
  147.                {    if ( zip[0] | zip[1] | zip[2] | zip[3] )
  148.                     goto notz;
  149.                }
  150.             zipb = (const byte *)zip;
  151.             while ( --zcnt >= 0 )
  152.                {
  153.                 if ( *zipb++ )
  154.                     goto notz;
  155.                }
  156.             /* Line is all zero, skip */
  157.             lnum++;
  158.             skip++;
  159.             continue;
  160. notz:            ;
  161.            }
  162.  
  163.         /* Vertical tab to the appropriate position.  Note here that
  164.            we make sure we don't move below limit. */
  165.         if ( lnum > limit )
  166.             {    skip -= (limit - lnum);
  167.             lnum = limit;
  168.             }
  169.  
  170.         /* The SJ48 can only skip in steps of 1/180" */
  171.         if (yres == 180) {
  172.           skips = skip;
  173.         } else {
  174.           if (skip & 1) {
  175.             skip--; /* Makes skip even. */
  176.             lnum--;
  177.           }
  178.                   skips = skip/2;
  179.         } 
  180.             
  181.         while ( skips > 255 )
  182.            {    fputs("\033J\377", prn_stream);
  183.             skips -= 255;
  184.            }
  185.         if ( skips )
  186.             fprintf(prn_stream, "\033J%c", skips);
  187.  
  188.         /* If we've printed as far as "limit", then reset "limit"
  189.            to "last_row" for the final printing pass. */
  190.         if ( lnum == limit )
  191.             limit = last_row;
  192.         skip = 0;
  193.  
  194.         /* Transpose in blocks of 8 scan lines. */
  195.         for ( bnum = 0; bnum < bits_per_column; bnum += 8 )
  196.            {    int lcnt = min(8, limit - lnum);
  197.             byte *inp = in;
  198.             byte *outp = outl;
  199.                lcnt = gdev_prn_copy_scan_lines(pdev,
  200.                 lnum, in, lcnt * line_size);
  201.             if ( lcnt < 0 )
  202.                {    code = lcnt;
  203.                 goto xit;
  204.                }
  205.             if ( lcnt < 8 )
  206.                 memset(in + lcnt * line_size, 0,
  207.                        (8 - lcnt) * line_size);
  208.             for ( ; inp < in_end; inp++, outp += bits_per_column )
  209.                {    gdev_prn_transpose_8x8(inp, line_size,
  210.                     outp, bytes_per_column);
  211.                }
  212.             outl++;
  213.             lnum += lcnt;
  214.             skip += lcnt;
  215.            }
  216.  
  217.         /* Send the bits to the printer.  We alternate horizontal
  218.            skips with the data.  The horizontal skips are in units
  219.            of 1/180 inches, so we look at the data in groups of
  220.            1 or 2 columns depending on resolution (controlled
  221.                    by skip_unit).  */
  222.         outl = out;
  223.         do
  224.            {    int count;
  225.             int n;
  226.             byte *out_ptr;
  227.  
  228.             /* First look for blank groups of columns. */
  229.             while(outl < out_end)
  230.                {    n = count = min(out_end - outl, skip_unit);
  231.                 out_ptr = outl;
  232.                 while ( --count >= 0 )
  233.                    {    if ( *out_ptr++ )
  234.                         break;
  235.                    }
  236.                 if ( count >= 0 )
  237.                     break;
  238.                 else
  239.                     outl = out_ptr;
  240.                }
  241.             if (outl >= out_end)
  242.                 break;
  243.             if (outl > out_beg)
  244.                {    count = (outl - out_beg) / skip_unit;
  245.                 fprintf(prn_stream, "\033\\%c%c",
  246.                     count & 0xff, count >> 8);
  247.                }
  248.  
  249.             /* Next look for non-blank groups of columns. */
  250.             out_beg = outl;
  251.             outl += n;
  252.             while(outl < out_end)
  253.                {    n = count = min(out_end - outl, skip_unit);
  254.                 out_ptr = outl;
  255.                 while ( --count >= 0 )
  256.                    {    if ( *out_ptr++ )
  257.                         break;
  258.                    }
  259.                 if ( count < 0 )
  260.                     break;
  261.                 else
  262.                     outl += n;
  263.                }
  264.             count = outl - out_beg;
  265.             {
  266.               /* What to transmit is the number of columns in the row.
  267.                  Compare this with the <Esc>|*-command wich expects the
  268.                  total number of bytes in the graphic row! */
  269.               int count1 = count/bytes_per_column;
  270.               fprintf(prn_stream, "\033*%c%c%c",
  271.                   mode, count1 & 0xff, count1 >> 8);
  272.             }
  273.             fwrite(out_beg, 1, count, prn_stream);
  274.             out_beg = outl;
  275.             outl += n;
  276.            }
  277.         while ( out_beg < out_end );
  278.  
  279.         fputc('\r', prn_stream);
  280.         skip = bits_per_column;  /* <CR> only moves to the beginning of the row. */
  281.        }
  282.  
  283.     /* Eject the page */
  284. xit:    fputc(014, prn_stream);    /* form feed */
  285.     fflush(prn_stream);
  286. fin:    if ( out != 0 )
  287.         gs_free((char *)out, bits_per_column, line_size,
  288.             "sj48_print_page(out)");
  289.     if ( in != 0 )
  290.         gs_free((char *)in, 8, line_size, "sj48_print_page(in)");
  291.     return code;
  292. }
  293.